#include <stdlib.h>
#include <stdio.h>
#include <nds.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>

// common headers
#include "common.h"

// local headers
#include "plugin.h"
#include "library.h"
#include "librarylist.h"
#include "extensionlist.h"
#include "improvedextensionlist.h"

#include "binarylist.h"

sLibLists liblists;
sIEL *extslist=NULL;

int initLists(LLIST **liblist, LLIST **pluglist) {
iprintf("\n1");
    {   // creating library list
        bzero(&liblists, sizeof(sLibLists));

        LLIST *last=NULL;
        struct dirent *ent;
        DIR *dir=opendir("/data/SunOS/libraries");
        if(dir) {
            while((ent=readdir(dir))) {
                if(cmpext(ent->d_name, ".sundll")) continue;
iprintf(",%s", basename(ent->d_name));

                sLibrary lib;
                bzero(&lib, sizeof(sLibrary));
                *strrchr(ent->d_name, '.')=0;
                strncpy(lib.name, ent->d_name, 128);

                sLibProc *lp=newLibInstance(&lib);
                if(!lp) {
iprintf("!");
                    continue;
                }
                lib.id=lp->query(QUERY_ID);
                EL_concat_copy(&lib.exts, (sEL *)lp->query(QUERY_FILEEXT));
                deleteLibInstance(lp);

                last=ll_append_el(&last, xmemdup(&lib, sizeof(sLibrary)));
                if(!liblists.all) liblists.all=last; // store the first element in liblists.all

                // add typed libraries to their list
                u8 type=ID2TYPE(SL(last)->id);
                if(type>=LIB_NUM_TYPES) iprintf("\nwarning: bad library type (%d>=%d)", type, LIB_NUM_TYPES);
                else LL_addLib(&liblists.lists[type], SL(last));
            }
            closedir(dir);

            if(liblist) *liblist=liblists.all;
        }
    }

iprintf("\n2");
    {    // creating plugin list
        LLIST *first=NULL, *last=NULL;
        struct dirent *ent;
        DIR *dir=opendir("/data/SunOS/plugins");
        if(dir) {
            while((ent=readdir(dir))) {
                if(!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)) continue;
iprintf(",%s", basename(ent->d_name));

                sPlugin plug;
                bzero(&plug, sizeof(sPlugin));
                strcpy(plug.name, ent->d_name);

                if(initPlugin(&plug)) {
iprintf("!");
                    continue;
                }

                last=ll_append_el(&last, xmemdup(&plug, sizeof(sPlugin)));
                if(!first) first=last;

            // <--    create an entry for each extension
                // begin with the library ids
                u32 *ids=(u32 *)plug.query(QUERY_IDS);
                if(ids)
                    while(*ids) {
                        LLIST *_cur=liblists.lists[ID2TYPE(*ids)];
                        while(_cur) {
                            if(ID2TYPE(*ids)!=tFUNCTIONS || (ID2TYPE(*ids)==tFUNCTIONS && *ids==SL(_cur)->id))
                                IEL_add_EL(&extslist, SL(_cur)->exts, SP(last));

                            _cur=_cur->next;
                        }

                        ids++;
                    }

                // finish with the exts of the app
                sEL *el=(sEL *)plug.query(QUERY_FILEEXT);
                if(el) IEL_add_copy_EL(&extslist, *el, SP(last));
            // -->

                deinitPlugin(SP(last));            
            }
            closedir(dir);

            if(pluglist) *pluglist=first;
        }
    }

//while(!(keysDown()&KEY_B)) swiWaitForVBlank();

// dump exts dict (contains all the supported exts)
    {
        sIEL *el=extslist;
        while(el) {
            iprintf("\n%s:%s", el->ext, el->plug->name);

            el=el->next;
        }
    }

    return 0;
}

